<!DOCTYPE html>
<html lang="en-US">
    <head>
        <title>Apache::MP3 - Generate streamable directories of MP3 and Ogg Vorbis files - metacpan.org</title>
        <link rel="preload" as="fetch" href="https://metacpan.org/account/login_status" crossorigin="anonymous" />
        <link href="https://metacpan.org/_assets/b8ccceeed47a0652049703d99326a9cea4933443.css" rel="stylesheet" type="text/css">
        <script src="https://metacpan.org/_assets/6bfedafe2d7caa915b7d84f61b45936818e3242e.js" type="text/javascript" defer></script>
        <link rel="alternate" type="application/rss+xml" title="Recent CPAN Uploads of Apache-MP3 - MetaCPAN" href="https://metacpan.org/dist/Apache-MP3/releases.rss" />
        <link rel="canonical" href="./Apache::MP3.html" />
        <meta name="description" content="Generate streamable directories of MP3 and Ogg Vorbis files" />
        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
        <link rel="shortcut icon" href="https://metacpan.org/static/icons/favicon.ico">
        <link rel="apple-touch-icon" sizes="152x152" href="https://metacpan.org/static/icons/apple-touch-icon.png">
        <link rel="search" href="https://metacpan.org/static/opensearch.xml" type="application/opensearchdescription+xml" title="MetaCPAN">
        <script>
          (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
          (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
          m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
          })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

          (function(skey, ga_id){
            ga('create', ga_id, {
              siteSpeedSampleRate : 100,
              storage             : 'none',
              clientId            : localStorage.getItem(skey)
            });
            ga(function(tracker) {
              localStorage.setItem(skey, tracker.get('clientId'));
            });
            ga('send', 'pageview');
          })('ga:clientId', 'UA-27829474-1');
        </script>
<meta name="twitter:card"        content="summary" />
<meta name="twitter:url"         content="https://metacpan.org/pod/Apache::MP3" />
<meta name="twitter:title"       content="Apache::MP3" />
<meta name="twitter:description" content="Generate streamable directories of MP3 and Ogg Vorbis files" />
<meta name="twitter:site"        content="metacpan" />
    </head>
    <body>
        <nav class="navbar navbar-default" role="navigation">
            <div class="header-logo-large hidden-xs">
              <a href="https://metacpan.org/" tabindex="0">
                <svg class="logo" aria-label="MetaCPAN">
                  <use class="logo" href="/static/images/metacpan-logo.svg#logo" />
                </svg>
              </a>
            </div>
            <div class="header-logo-icon visible-xs">
              <a href="https://metacpan.org/">
                <svg class="logo" aria-label="MetaCPAN">
                  <use class="logo" href="/static/images/metacpan-logo.svg#dots" />
                </svg>
              </a>
            </div>
            <ul class="nav navbar-nav menu-items hidden-xs hidden-sm">
              <li><a href="https://metacpan.org/about">About</a></li>
              <li><a href="https://metacpan.org/about/sponsors">Sponsor</a></li>
              <li><a href="https://grep.metacpan.org/">grep::cpan</a></li>
              <li><a href="https://metacpan.org/recent">Recent</a></li>
              <li><a href="https://metacpan.org/about/faq">FAQ</a></li>
              <li><a href="https://metacpan.org/tools">Tools</a></li>
              <li><a href="https://fastapi.metacpan.org/">API</a></li>
            </ul>
            <ul class="nav navbar-nav navbar-right">
                <button type="button" class="searchbar-btn visible-xs visible-sm">
                    <i class="fa fa-search button-fa-icon"></i>
                </button>
                <form action="https://metacpan.org/search" class="searchbar-form visible-md visible-lg search-form form-horizontal">
                   <input type="hidden" name="size" id="metacpan_search-size" value="20">
                  <div class="form-group">
                      <div class="search-group">
                        <i class="fa fa-search"></i>
                        <input type="text" name="q" placeholder="Search the CPAN" size="41" autocorrect="off" autocapitalize="off" spellcheck="false" id="metacpan_search-input" class="form-control" value="">
                      </div>
                  </div>
                </form>
                    <li class="icon-slidepanel visible-xs visible-sm">
                      <button data-toggle="slidepanel" data-target=".slidepanel">
                        <span class="button-fa-icon">
                          <i class="fa fa-bars slidepanel-open"></i>
                          <i class="fa fa-times slidepanel-close"></i>
                        </span>
                      </button>
                    </li>
                <form action="https://metacpan.org/account/logout" method="POST" id="metacpan-logout"></form>
                <li class="dropdown logged_in" style="display: none;">
                    <button type="button" class="dropdown-toggle" data-toggle="dropdown">
                      <i class="fa fa-user button-fa-icon logged-in-icon" aria-hidden="true"></i>
                      <i class="fas fa-chevron-down"></i>
                    </button>
                    <ul class="dropdown-menu">
                        <li><a href="https://metacpan.org/account/identities">Identities</a></li>
                        <li><a href="https://metacpan.org/account/profile">Profile</a></li>
                        <li><a href="https://metacpan.org/account/favorite/list">Favorites</a></li>
                        <li>
                            <a href="./Apache::MP3.html#" type="button" onclick="$('#metacpan-logout').submit(); return false">
                              Logout
                            </a>
                        </li>
                    </ul>
                </li>
                <li class="dropdown logged_out" style="display: none;">
                    <button type="button" class="dropdown-toggle" data-toggle="dropdown">
                      <i class="fa fa-user button-fa-icon" aria-hidden="true"></i>
                      <i class="fas fa-chevron-down"></i>
                    </button>
                    <ul class="dropdown-menu">
                        <li>
                            <a href="https://metacpan.org/login/github">
                                <i class="fab fa-github fa-fw"></i>
                                GitHub
                            </a>
                        </li>
                        <li>
                            <a href="https://metacpan.org/login/twitter">
                                <i class="fab fa-twitter fa-fw"></i>
                                Twitter
                            </a>
                        </li>
                        <li>
                            <a href="https://metacpan.org/login/google">
                                <i class="fab fa-google fa-fw"></i>
                                Google
                            </a>
                        </li>
                    </ul>
                </li>
                <li class="dropdown logged_placeholder">
                    <button>
                      <i class="fa fa-user button-fa-icon" aria-hidden="true"></i>
                    </button>
                </li>
            </ul>
        </nav>
        <div class="page-content ">
          <!--
          <div class="top-notify-banner">
            <i class="fas fa-info-circle"></i>
          </div>
          -->
          <nav class="sidebar">
            <div class="slidepanel">
              <ul class="nav-list ">
    <li class="nav-header no-margin-top">
      <div class="ttip" data-toggle="tooltip" data-placement="bottom" title="The date that this version of Apache-MP3 was released.">
      <span class="relatize">15 Apr 2006 01:26:38 UTC</span>
    </li>
  <li>
    Distribution: <a href="https://metacpan.org/dist/Apache-MP3">Apache-MP3</a>
  </li>
  <li>
    Module version: 3.06
  </li>
  <li>
    <a data-keyboard-shortcut="g s" href="https://metacpan.org/dist/Apache-MP3/source/MP3.pm">Source</a>
    (<a href="https://metacpan.org/dist/Apache-MP3/source/MP3.pm?raw=1">raw</a>)
  </li>
  <li>
    <a data-keyboard-shortcut="g b" href="https://metacpan.org/dist/Apache-MP3/source">Browse</a>
    (<a href="https://metacpan.org/dist/Apache-MP3/source?raw=1">raw</a>)
  </li>
    <li>
      <a data-keyboard-shortcut="g c" href="https://metacpan.org/dist/Apache-MP3/changes">Changes</a>
    </li>
    <li>
      <a class="nopopup" href="https://metacpan.org/dist/Apache-MP3/contribute">How to Contribute</a>
    </li>
    <li>
      <a rel="noopener nofollow" data-keyboard-shortcut="g i" href="https://rt.cpan.org/Public/Dist/Display.html?Name=Apache-MP3">Issues</a>
      (2)
    </li>
    <li>
      <a rel="noopener nofollow" href="http://matrix.cpantesters.org/?dist=Apache-MP3+4.00" title="Matrix">Testers</a>
        <span title="(pass / fail / na)">(<a rel="noopener nofollow" href="https://www.cpantesters.org/distro/A/Apache-MP3.html?oncpan=1&amp;distmat=1&amp;version=4.00&amp;grade=2" style="color: #090">22</a> / <a rel="noopener nofollow" href="https://www.cpantesters.org/distro/A/Apache-MP3.html?oncpan=1&amp;distmat=1&amp;version=4.00&amp;grade=3" style="color: #900">0</a> / <a rel="noopener nofollow" href="https://www.cpantesters.org/distro/A/Apache-MP3.html?oncpan=1&amp;distmat=1&amp;version=4.00&amp;grade=4">0</a>)</span>
    </li>
    <li>
      <a rel="noopener nofollow" href="http://cpants.cpanauthors.org/release/LDS/Apache-MP3-4.00">Kwalitee</a>
    </li>
    <li>
      <div class="ttip" data-toggle="tooltip" data-placement="bottom" title="The # people with an indexing permission on Apache-MP3 who have released something to CPAN in the last 2 years (i.e. the # people likely able to release critical fixes in a timely manner)">
      Bus factor: 0
      </div>
    </li>
    <li>
      <a rel="noopener nofollow" href="http://cpancover.com/latest/Apache-MP3-4.00/index.html">% Coverage </a>
    </li>
    <li>
      License: unknown
    </li>
    <li class="nav-header">Activity</li>
    <li>
<div class="activity-graph">
    <img src="https://metacpan.org/dist/Apache-MP3/activity.svg?res=month" />
    <div class="comment">24 month</div>
</div>
    </li>
    <li class="nav-header">Tools</li>
    <li>
      <a itemprop="downloadUrl" href="https://cpan.metacpan.org/authors/id/L/LD/LDS/Apache-MP3-4.00.tar.gz">
      Download (<span itemprop="fileSize">320.69KB</span>)</a>
    </li>
    <li>
      <a href="https://explorer.metacpan.org/?url=%2Fmodule%2FLDS%2FApache-MP3-4.00%2FMP3.pm">
        MetaCPAN Explorer
      </a>
    </li>
    <li>
      <a href="https://metacpan.org/dist/Apache-MP3/permissions">
        Permissions
      </a>
    </li>
    <li>
      <a href="https://metacpan.org/dist/Apache-MP3/releases.rss">
        Subscribe to distribution
      </a>
    </li>
    <li>
      <button class="btn btn-link" data-toggle="modal" data-target="#metacpan_install-instructions-dialog">
        Install Instructions
      </button>
    </li>
    <li>
      <form action="https://metacpan.org/search">
        <input type="hidden" name="q" value="dist:Apache-MP3">
        <input type="search" name="q" placeholder="Search distribution" class="form-control tool-bar-form">
        <input type="submit" style="display: none">
      </form>
    </li>
    <li>
      <form action="https://grep.metacpan.org/search">
        <input type="hidden" name="qd" value="Apache-MP3">
        <input type="hidden" name="source" value="metacpan">
        <input type="search" name="q" placeholder="grep distribution" class="form-control tool-bar-form">
        <input type="submit" style="display: none">
     </form>
    </li>
    <li class="version-jump">
<select onchange="document.location.href=&#39;/release/&#39;+this.value+&#39;/view/MP3.pm&#39;" class="form-control tool-bar-form">
  <option disabled selected>Jump to version</option>
<option
  disabled
  value="LDS/Apache-MP3-4.00"
>4.00
  (LDS on 2006-04-15)</option>
<option
  
  value="LDS/Apache-MP3-3.05"
>3.05
  (LDS on 2003-10-06)</option>
<option
  
  value="LDS/Apache-MP3-3.04"
>3.04
  (LDS on 2003-02-15)</option>
<option
  
  value="LDS/Apache-MP3-3.03"
>3.03
  (LDS on 2002-10-14)</option>
<option
  
  value="LDS/Apache-MP3-3.01"
>3.01
  (LDS on 2002-08-18)</option>
<option
  
  value="LDS/Apache-MP3-3.00"
>3.00
  (LDS on 2002-08-16)</option>
<option
  
  value="LDS/Apache-MP3-2.26"
>2.26
  (LDS on 2002-05-31)</option>
<option
  
  value="LDS/Apache-MP3-1.00"
>1.00
  (LDS on 2000-03-20)</option>
<optgroup label="BackPAN">'
<option
  
  value="LDS/Apache-MP3-2.22"
>2.22
  (LDS on 2002-01-06)</option>
<option
  
  value="LDS/Apache-MP3-2.20"
>2.20
  (LDS on 2001-09-26)</option>
<option
  
  value="LDS/Apache-MP3-2.19"
>2.19
  (LDS on 2001-07-17)</option>
<option
  
  value="LDS/Apache-MP3-2.18"
>2.18
  (LDS on 2001-06-10)</option>
<option
  
  value="LDS/Apache-MP3-2.16"
>2.16
  (LDS on 2001-05-01)</option>
<option
  
  value="LDS/Apache-MP3-2.15"
>2.15
  (LDS on 2001-01-02)</option>
<option
  
  value="LDS/Apache-MP3-2.14"
>2.14
  (LDS on 2000-12-31)</option>
<option
  
  value="LDS/Apache-MP3-2.12"
>2.12
  (LDS on 2000-11-21)</option>
<option
  
  value="LDS/Apache-MP3-2.11"
>2.11
  (LDS on 2000-09-09)</option>
<option
  
  value="LDS/Apache-MP3-2.10"
>2.10
  (LDS on 2000-09-03)</option>
<option
  
  value="LDS/Apache-MP3-2.08"
>2.08
  (LDS on 2000-08-31)</option>
<option
  
  value="LDS/Apache-MP3-2.06"
>2.06
  (LDS on 2000-08-26)</option>
<option
  
  value="LDS/Apache-MP3-2.05"
>2.05
  (LDS on 2000-08-25)</option>
<option
  
  value="LDS/Apache-MP3-2.04"
>2.04
  (LDS on 2000-08-23)</option>
<option
  
  value="LDS/Apache-MP3-2.02"
>2.02
  (LDS on 2000-05-28)</option>
<option
  
  value="LDS/Apache-MP3-2.01"
>2.01
  (LDS on 2000-05-27)</option>
<option
  
  value="LDS/Apache-MP3-2.00"
>2.00
  (LDS on 2000-05-27)</option>
</optgroup>
</select>
    </li>
    <li class="version-diff">
<select onchange="document.location.href='/release/LDS/Apache-MP3-4.00/diff/' + encodeURIComponent(this.value) + '/MP3.pm'
" class="form-control tool-bar-form">
  <option disabled selected>Diff with version</option>
<option
  disabled
  value="LDS/Apache-MP3-4.00"
>4.00
  (LDS on 2006-04-15)</option>
<option
  
  value="LDS/Apache-MP3-3.05"
>3.05
  (LDS on 2003-10-06)</option>
<option
  
  value="LDS/Apache-MP3-3.04"
>3.04
  (LDS on 2003-02-15)</option>
<option
  
  value="LDS/Apache-MP3-3.03"
>3.03
  (LDS on 2002-10-14)</option>
<option
  
  value="LDS/Apache-MP3-3.01"
>3.01
  (LDS on 2002-08-18)</option>
<option
  
  value="LDS/Apache-MP3-3.00"
>3.00
  (LDS on 2002-08-16)</option>
<option
  
  value="LDS/Apache-MP3-2.26"
>2.26
  (LDS on 2002-05-31)</option>
<option
  
  value="LDS/Apache-MP3-1.00"
>1.00
  (LDS on 2000-03-20)</option>
<optgroup label="BackPAN">'
<option
  
  value="LDS/Apache-MP3-2.22"
>2.22
  (LDS on 2002-01-06)</option>
<option
  
  value="LDS/Apache-MP3-2.20"
>2.20
  (LDS on 2001-09-26)</option>
<option
  
  value="LDS/Apache-MP3-2.19"
>2.19
  (LDS on 2001-07-17)</option>
<option
  
  value="LDS/Apache-MP3-2.18"
>2.18
  (LDS on 2001-06-10)</option>
<option
  
  value="LDS/Apache-MP3-2.16"
>2.16
  (LDS on 2001-05-01)</option>
<option
  
  value="LDS/Apache-MP3-2.15"
>2.15
  (LDS on 2001-01-02)</option>
<option
  
  value="LDS/Apache-MP3-2.14"
>2.14
  (LDS on 2000-12-31)</option>
<option
  
  value="LDS/Apache-MP3-2.12"
>2.12
  (LDS on 2000-11-21)</option>
<option
  
  value="LDS/Apache-MP3-2.11"
>2.11
  (LDS on 2000-09-09)</option>
<option
  
  value="LDS/Apache-MP3-2.10"
>2.10
  (LDS on 2000-09-03)</option>
<option
  
  value="LDS/Apache-MP3-2.08"
>2.08
  (LDS on 2000-08-31)</option>
<option
  
  value="LDS/Apache-MP3-2.06"
>2.06
  (LDS on 2000-08-26)</option>
<option
  
  value="LDS/Apache-MP3-2.05"
>2.05
  (LDS on 2000-08-25)</option>
<option
  
  value="LDS/Apache-MP3-2.04"
>2.04
  (LDS on 2000-08-23)</option>
<option
  
  value="LDS/Apache-MP3-2.02"
>2.02
  (LDS on 2000-05-28)</option>
<option
  
  value="LDS/Apache-MP3-2.01"
>2.01
  (LDS on 2000-05-27)</option>
<option
  
  value="LDS/Apache-MP3-2.00"
>2.00
  (LDS on 2000-05-27)</option>
</optgroup>
</select>
    </li>

    <li>
<ul class="dependencies">
  <li class="nav-header">Dependencies</li>
  <li><a href="https://metacpan.org/pod/Apache2::RequestRec" title="Apache2::RequestRec" class="ellipsis">Apache2::RequestRec</a></li>
  <li><a href="https://metacpan.org/pod/Audio::Wav" title="Audio::Wav" class="ellipsis">Audio::Wav</a></li>
  <li><a href="https://metacpan.org/pod/CGI::Session" title="CGI::Session" class="ellipsis">CGI::Session</a></li>
  <li><a href="https://metacpan.org/pod/Inline::MakeMaker" title="Inline::MakeMaker" class="ellipsis">Inline::MakeMaker</a></li>
  <li><a href="https://metacpan.org/pod/Locale::Maketext" title="Locale::Maketext" class="ellipsis">Locale::Maketext</a></li>
  <li><a href="https://metacpan.org/pod/MP3::Info" title="MP3::Info" class="ellipsis">MP3::Info</a></li>
  <li><a href="https://metacpan.org/pod/Ogg::Vorbis::Header" title="Ogg::Vorbis::Header" class="ellipsis">Ogg::Vorbis::Header</a></li>
  <li><i class="ttip" title="dynamic_config enabled">and possibly others</i></li>
  <li>
    <hr>
  </li>
  <li>
    <a href="https://metacpan.org/module/Apache::MP3/requires">Reverse dependencies</a>
  </li>
  <li>
    <a href="http://deps.cpantesters.org/?module=Apache%3A%3AMP3">CPAN Testers List</a>
  </li>
  <li>
    <a href="https://cpandeps.grinnz.com/?dist=Apache-MP3">Dependency graph</a>
  </li>
</ul>
    </li>
    <li class="nav-header">Permalinks</li>
    <li>
      <a href="https://metacpan.org/release/LDS/Apache-MP3-4.00/view/MP3.pm">This version</a>
    </li>
    <li>
      <a href="./Apache::MP3.html">Latest version</a>
    </li>
    <li>
    </li>
    <li>
    </li>
              </ul>
            </div>
          </nav>
          <div class="content-navigation">
<div class="breadcrumbs">
  <span>
    <a data-keyboard-shortcut="g a" rel="author" href="https://metacpan.org/author/LDS" class="author-name">Lincoln D. Stein</a>
  </span>
  <span>&nbsp;/&nbsp;</span>
  <div class="release dist-release status-latest maturity-released">
    <span class="dropdown"><b class="caret"></b></span>
<select onchange="document.location.href=&#39;/release/&#39;+this.value+&#39;/view/MP3.pm&#39;" class="">
<option
  selected
  value="LDS/Apache-MP3-4.00"
>4.00
  (LDS on 2006-04-15)</option>
<option
  
  value="LDS/Apache-MP3-3.05"
>3.05
  (LDS on 2003-10-06)</option>
<option
  
  value="LDS/Apache-MP3-3.04"
>3.04
  (LDS on 2003-02-15)</option>
<option
  
  value="LDS/Apache-MP3-3.03"
>3.03
  (LDS on 2002-10-14)</option>
<option
  
  value="LDS/Apache-MP3-3.01"
>3.01
  (LDS on 2002-08-18)</option>
<option
  
  value="LDS/Apache-MP3-3.00"
>3.00
  (LDS on 2002-08-16)</option>
<option
  
  value="LDS/Apache-MP3-2.26"
>2.26
  (LDS on 2002-05-31)</option>
<option
  
  value="LDS/Apache-MP3-1.00"
>1.00
  (LDS on 2000-03-20)</option>
<optgroup label="BackPAN">'
<option
  
  value="LDS/Apache-MP3-2.22"
>2.22
  (LDS on 2002-01-06)</option>
<option
  
  value="LDS/Apache-MP3-2.20"
>2.20
  (LDS on 2001-09-26)</option>
<option
  
  value="LDS/Apache-MP3-2.19"
>2.19
  (LDS on 2001-07-17)</option>
<option
  
  value="LDS/Apache-MP3-2.18"
>2.18
  (LDS on 2001-06-10)</option>
<option
  
  value="LDS/Apache-MP3-2.16"
>2.16
  (LDS on 2001-05-01)</option>
<option
  
  value="LDS/Apache-MP3-2.15"
>2.15
  (LDS on 2001-01-02)</option>
<option
  
  value="LDS/Apache-MP3-2.14"
>2.14
  (LDS on 2000-12-31)</option>
<option
  
  value="LDS/Apache-MP3-2.12"
>2.12
  (LDS on 2000-11-21)</option>
<option
  
  value="LDS/Apache-MP3-2.11"
>2.11
  (LDS on 2000-09-09)</option>
<option
  
  value="LDS/Apache-MP3-2.10"
>2.10
  (LDS on 2000-09-03)</option>
<option
  
  value="LDS/Apache-MP3-2.08"
>2.08
  (LDS on 2000-08-31)</option>
<option
  
  value="LDS/Apache-MP3-2.06"
>2.06
  (LDS on 2000-08-26)</option>
<option
  
  value="LDS/Apache-MP3-2.05"
>2.05
  (LDS on 2000-08-25)</option>
<option
  
  value="LDS/Apache-MP3-2.04"
>2.04
  (LDS on 2000-08-23)</option>
<option
  
  value="LDS/Apache-MP3-2.02"
>2.02
  (LDS on 2000-05-28)</option>
<option
  
  value="LDS/Apache-MP3-2.01"
>2.01
  (LDS on 2000-05-27)</option>
<option
  
  value="LDS/Apache-MP3-2.00"
>2.00
  (LDS on 2000-05-27)</option>
</optgroup>
</select>
    <a data-keyboard-shortcut="g d" class="release-name" href="https://metacpan.org/dist/Apache-MP3">Apache-MP3-4.00</a>
  </div>
<span class="river-gauge-gauge">
  <svg width="24px"
       height="15px"
       version="1.1"
       xmlns="http://www.w3.org/2000/svg"
       xmlns:xlink="http://www.w3.org/1999/xlink">

    <g>
      <title>        River stage zero &#10;
          No dependents
      </title>

      <rect x="0"  y="0" width="4" height="15" fill="#e4e2e2" />
      <rect x="5"  y="0" width="4" height="15" fill="#e4e2e2" />
      <rect x="10"  y="0" width="4" height="15" fill="#e4e2e2" />
      <rect x="15"  y="0" width="4" height="15" fill="#e4e2e2" />
      <rect x="20"  y="0" width="4" height="15" fill="#e4e2e2" />
    </g>
  </svg>

</span>
<div id="Apache-MP3-fav" class="logged_in">
<form action="https://metacpan.org/account/favorite/add" style="display: inline" onsubmit="return favDistribution(this)">
    <input type="hidden" name="remove" value="0">
    <input type="hidden" name="release" value="Apache-MP3-4.00">
    <input type="hidden" name="author" value="LDS">
    <input type="hidden" name="distribution" value="Apache-MP3">
    <button type="submit" class="favorite"><span></span> ++</button>
</form>
</div>
<div class="logged_out">
<a href="./Apache::MP3.html" onclick="alert('Please sign in to add favorites'); return false" class="favorite">
<span></span> ++</a>
</div>
   / <span>Apache::MP3</span>
</div>
          </div>
          <main class="content">


<nav class="toc">
  <div class="toc-header"><strong>Contents</strong></div>
<ul>
  <li><a href="./Apache::MP3.html#NAME">NAME</a></li>
  <li><a href="./Apache::MP3.html#SYNOPSIS">SYNOPSIS</a></li>
  <li><a href="./Apache::MP3.html#DESCRIPTION">DESCRIPTION</a>
    <ul>
      <li><a href="./Apache::MP3.html#Installation">Installation</a></li>
    </ul>
  </li>
  <li><a href="./Apache::MP3.html#CUSTOMIZING">CUSTOMIZING</a>
    <ul>
      <li><a href="./Apache::MP3.html#Per-directory-configuration-variables">Per-directory configuration variables</a></li>
      <li><a href="./Apache::MP3.html#General-Configuration-Variables">General Configuration Variables</a></li>
      <li><a href="./Apache::MP3.html#Configuration-Variables-Affecting-Paths-and-Directories">Configuration Variables Affecting Paths and Directories</a></li>
      <li><a href="./Apache::MP3.html#Configuration-Variables-Affecting-the-Visual-Display">Configuration Variables Affecting the Visual Display</a></li>
      <li><a href="./Apache::MP3.html#Stylesheet-Based-Configuration">Stylesheet-Based Configuration</a></li>
      <li><a href="./Apache::MP3.html#Subclassing-this-Module">Subclassing this Module</a></li>
    </ul>
  </li>
  <li><a href="./Apache::MP3.html#Linking-to-this-module">Linking to this module</a></li>
  <li><a href="./Apache::MP3.html#The-Apache::MP3-API">The Apache::MP3 API</a>
    <ul>
      <li><a href="./Apache::MP3.html#Method-Calls">Method Calls</a></li>
    </ul>
  </li>
  <li><a href="./Apache::MP3.html#BUGS">BUGS</a>
    <ul>
      <li><a href="./Apache::MP3.html#Random-segfaults-in-httpd-children">Random segfaults in httpd children</a></li>
      <li><a href="./Apache::MP3.html#Can&#39;t-use-d-$r-%3Efinfo">Can&#39;t use -d $r-&gt;finfo</a></li>
      <li><a href="./Apache::MP3.html#Misc">Misc</a></li>
    </ul>
  </li>
  <li><a href="./Apache::MP3.html#SEE-ALSO">SEE ALSO</a></li>
  <li><a href="./Apache::MP3.html#ACKNOWLEDGEMENTS">ACKNOWLEDGEMENTS</a></li>
  <li><a href="./Apache::MP3.html#AUTHOR">AUTHOR</a></li>
</ul></nav>
<div class="pod anchors">
<h1 id="NAME">NAME</h1>

<p>Apache::MP3 - Generate streamable directories of MP3 and Ogg Vorbis files</p>

<h1 id="SYNOPSIS">SYNOPSIS</h1>

<pre><code> # httpd.conf or srm.conf
 AddType audio/mpeg     mp3 MP3
 AddType audio/playlist m3u M3U
 AddType audio/x-scpls  pls PLS
 AddType application/x-ogg ogg OGG

 # httpd.conf or access.conf
 &lt;Location /songs&gt;
   SetHandler perl-script
   PerlHandler Apache::MP3
 &lt;/Location&gt;

  # Or use the Apache::MP3::Sorted subclass to get sortable directory listings
 &lt;Location /songs&gt;
   SetHandler perl-script
   PerlHandler Apache::MP3::Sorted
 &lt;/Location&gt;

  # Or use the Apache::MP3::Playlist subclass to get persistent playlists
 &lt;Location /songs&gt;
   SetHandler perl-script
  PerlHandler Apache::MP3::Playlist
 &lt;/Location&gt;</code></pre>

<p>A <b>demo version</b> can be browsed at http://www.modperl.com/Songs/.</p>

<h1 id="DESCRIPTION">DESCRIPTION</h1>

<p>This module makes it possible to browse a directory hierarchy containing MP3, Ogg Vorbis, or Wav files, sort them on various fields, download them, stream them to an MP3 decoder like WinAmp, and construct playlists. The display is configurable and subclassable.</p>

<p>NOTE: This version of Apache::MP3 is substantially different from the pre-2.0 version described in The Perl Journal. Specifically, the format to use for HREF links has changed. See <i>Linking</i> for details.</p>

<h2 id="Installation">Installation</h2>

<p>This section describes the installation process.</p>

<dl>

<dt id="1.-Prequisites"><a id="1"></a><a id="Prequisites"></a>1. Prequisites</dt>
<dd>

<p>This module requires mod_perl, MP3::Info (to stream MP3 files), Ogg::Vorbis (to stream OggVorbis files), and Audio::Wav (for Wave files) all of which are available on CPAN.</p>

<p>The module will automatically adjust for the absence of one or more of the MP3::Info, Ogg::Vorbis or Audio::Wav modules by inhibiting the display of the corresponding file type.</p>

</dd>
<dt id="2.-Configure-MIME-types"><a id="2"></a><a id="Configure-MIME-types"></a>2. Configure MIME types</dt>
<dd>

<p>Apache must be configured to recognize the mp3 and MP3 extensions as MIME type audio/mpeg. Add the following to httpd.conf or srm.conf:</p>

<pre><code> AddType audio/mpeg mp3 MP3
 AddType audio/playlist m3u M3U
 AddType audio/x-scpls  pls PLS
 AddType application/x-ogg ogg OGG
 AddType audio/wav wav WAV</code></pre>

<p>Note that you need extemely large amounts of bandwidth to stream Wav files, and that few audio file players currently support this type of streaming. Wav file support is primarily intended to allow for convenient downloads.</p>

</dd>
<dt id="3.-Install-icons-and-stylesheet"><a id="3"></a><a id="Install-icons-and-stylesheet"></a>3. Install icons and stylesheet</dt>
<dd>

<p>This module uses a set of icons and a cascading stylesheet to generate its song listings. By default, the module expects to find them at the url /apache_mp3. Create a directory named apache_mp3 in your document root, and copy into it the contents of the <i>apache_mp3</i> directory from the Apache-MP3 distribution.</p>

<p>You may change the location of this directory by setting the <i>BaseDir</i> configuration variable. See the <i>Customizing</i> section for more details.</p>

</dd>
<dt id="4.-Set-Apache::MP3-to-be-the-handler-for-the-MP3-directory"><a id="4"></a><a id="Set-Apache::MP3-to-be-the-handler-for-the-MP3-directory"></a>4. Set Apache::MP3 to be the handler for the MP3 directory</dt>
<dd>

<p>In httpd.conf or access.conf, create a &lt;Location&gt; or &lt;Directory&gt; section, and make Apache::MP3 the handler for this directory. This example assumes you are using the URL /Songs as the directory where you will be storing song files:</p>

<pre><code>  &lt;Location /Songs&gt;
    SetHandler perl-script
    PerlHandler Apache::MP3
  &lt;/Location&gt;</code></pre>

<p>If you would prefer an MP3 file listing that allows the user to sort it in various ways, set the handler to use the Apache::MP3::Sorted subclass instead. A further elaboration is Apache::MP3::Playlist, which uses cookies to manage a persistent playlist for the user.</p>

</dd>
<dt id="5.-Load-MP3::Info-in-the-Perl-Startup-file-(optional)"><a id="5"></a><a id="Load-MP3::Info-in-the-Perl-Startup-file--optional"></a>5. Load MP3::Info in the Perl Startup file (optional)</dt>
<dd>

<p>For the purposes of faster startup and memory efficiency, you may load the MP3::Info module at server startup time. If you have a mod_perl &quot;startup&quot; file, enter these lines:</p>

<pre><code>  use MP3::Info;
  use Apache::MP3;</code></pre>

</dd>
<dt id="6.-Set-up-MP3-directory"><a id="6"></a><a id="Set-up-MP3-directory"></a>6. Set up MP3 directory</dt>
<dd>

<p>Create a directory in the web server document tree that will contain the MP3 files to be served. The module recognizes and handles subdirectories appropriately. I suggest organizing directories hierarchically by artist and/or album name.</p>

<p>If you place a file named &quot;cover.jpg&quot; in any of the directories, that image will be displayed at the top of the directory listing. You can use this to display cover art.</p>

<p>If you place a list of .mp3 file names in a file with the .m3u extension, it will be treated as a playlist and displayed to the user with a distinctive icon. Selecting the playlist icon will download the playlist and stream its contents. The playlist must contain relative file names, but may refer to subdirectories, as in this example:</p>

<pre><code>  # file: folk_favorites.m3u
  Never_a_Moment_s_Thought_v2.mp3
  Peter Paul &amp; Mary - Leaving On A Jet Plane.mp3
  Simon and Garfunkel/Simon And Garfunkel - April Come She Will.mp3</code></pre>

<p>Likewise, if you place a list of shoutcast URLs into a file with the pls extension, it will be treated as a playlist and displayed to the user with a distinctive icon. Selecting the playlist icon will contact the shoutcast servers in the playlist and stream their contents. The playlist syntax is as in this example:</p>

<pre><code>  [playlist]
  numberofentries=2
  File1=http://205.188.245.132:8038
  Title1=Monkey Radio: Grooving. Sexy. Beats.
  Length1=-1
  File2=http://205.188.234.67:8052
  Title2=SmoothJazz
  Length2=-1
  Version=2</code></pre>

<p>Example shoutcast files can be downloaded from http://www.shoutcast.com You can find a lot of good MP3 broadcasts there, most of them commercial-free.</p>

<p>Apache::MP3 permits you to directly use CDDB data without embedding it in ID3 tags. To take advantage of this feature, your MP3 files should have file names of this form: track-XX.mp3. Then, place a CDDB index file in the same directory as the tracks and name it INDEX. For example, you might execute this command</p>

<pre><code>  cddbcmd cddb read soundtrack cb115c11 &gt; INDEX</code></pre>

<p>to create an INDEX file for the Mulholland Drive soundtrack. The 32-bit disc ID can be obtained with a program such as cd-discid.</p>

</dd>
<dt id="8.-Set-up-an-information-cache-directory-(optional)"><a id="8"></a><a id="Set-up-an-information-cache-directory--optional"></a>8. Set up an information cache directory (optional)</dt>
<dd>

<p>In order to generate its MP3 listing, Apache::MP3 must open each sound file, extract its header information, and close it. This is time consuming, particularly when recursively generating playlists across multiple directories. To speed up this process, Apache::MP3 has the ability cache MP3 file information in a separate directory area.</p>

<p>To configure this, choose a directory that the Web server has write access for, such as /usr/tmp. Then add a configuration variable like the following to the &lt;Location&gt; directive:</p>

<pre><code> PerlSetVar  CacheDir       /usr/tmp/mp3_cache</code></pre>

<p>If the designated directory does not exist, Apache::MP3 will attempt to create it, limited of course by the Web server&#39;s privileges. You may need to create the mp3_cache directory yourself if /usr/tmp is not world writable.</p>

</dd>
</dl>

<p>Open up the MP3 URL in your favorite browser. You should be able to see directory listings, and download and stream your songs. If things don&#39;t seem to be working, checking the server error log for messages.</p>

<h1 id="CUSTOMIZING">CUSTOMIZING</h1>

<p>Apache::MP3 can be customized in three ways: (1) by changing per-directory variables; (2) changing settings in the Apache::MP3 cascading stylesheet; and (3) subclassing Apache::MP3 or Apache::MP3::Sorted.</p>

<h2 id="Per-directory-configuration-variables"><a id="Per"></a>Per-directory configuration variables</h2>

<p>Per-directory variables are set by <i>PerlSetVar</i> directives in the Apache::MP3 &lt;Location&gt; or &lt;Directory&gt; section. For example, to change the icon displayed next to subdirectories of MP3s, you would use <i>PerlSetVar</i> to change the <i>DirectoryIcon</i> variable:</p>

<pre><code>  PerlSetVar DirectoryIcon big_cd.gif</code></pre>

<p>This following table summarizes the configuration variables. A more detailed explanation of each follows in the subsequent sections.</p>

<p>Table 1: Configuration Variables</p>

<pre><code> Name                  Value            Default
 ----                  -----            -------
 GENERAL OPTIONS
 AllowDownload         yes|no           yes
 AllowStream           yes|no           yes
 AllowPlayLocally      yes|no           yes
 CheckStreamClient     yes|no           no
 ReadMP3Info           yes|no           yes
 StreamTimeout         integer          0

 DIRECTORY OPTIONS
 BaseDir               URL              /apache_mp3
 CacheDir              path             -none-
 HelpImgURL            URL              apache_mp3_fig1.gif:374x292
 StreamBase            URL              -none-
 LocalNet              subnet           -none-

 DISPLAY OPTIONS
 ArrowIcon             URL              right_arrow.gif
 CoverImage            filename         cover.jpg
 CoverImageSmall       filename         cover_small.jpg
 PlaylistImage         filename         playlist.jpg
 DescriptionFormat     string           -see below-
 DirectoryIcon         URL              cd_icon_small.gif
 PlaylistIcon          URL              playlist.gif
 Fields                list             title,artist,duration,bitrate
 HomeLabel             string           &quot;Home&quot; (or translation)
 LongList              integer          10
 MissingComment        string           &quot;unknown&quot; (or translation)
 PathStyle             Staircase|Arrows|Slashes Staircase
 SongIcon              URL              sound.gif
 SubdirColumns         integer          1
 Stylesheet            URL              apache_mp3.css
 TitleIcon             URL              cd_icon.gif
 DefaultLanguage       languagetag      en-US</code></pre>

<h2 id="General-Configuration-Variables"><a id="General"></a>General Configuration Variables</h2>

<dl>

<dt id="AllowDownload-yes|no"><a id="AllowDownload"></a><a id="AllowDownload-yes-no"></a>AllowDownload <i>yes|no</i></dt>
<dd>

<p>You may wish for users to be able to stream songs but not download them to their local disk. If you set AllowDownload to &quot;no&quot;, Apache::MP3 will not generate a download link for MP3 files. It will also activate some code that makes it inconvenient (but not impossible) for users to download the MP3s.</p>

<p>The module recognizes the arguments &quot;yes&quot;, &quot;no&quot;, &quot;true&quot; and &quot;false&quot;. The default is &quot;yes&quot;.</p>

<p>Note that this setting only affects MP3 files. Other files, including cover art and playlists, can still be downloaded.</p>

</dd>
<dt id="AllowStream-yes|no"><a id="AllowStream"></a><a id="AllowStream-yes-no"></a>AllowStream <i>yes|no</i></dt>
<dd>

<p>If you set AllowStream to &quot;no&quot;, users will not be able to stream songs or generate playlists. I am not sure why one would want this feature, but it is included for completeness. The default is &quot;yes.&quot;</p>

</dd>
<dt id="AllowPlayLocally-yes|no"><a id="AllowPlayLocally"></a><a id="AllowPlayLocally-yes-no"></a>AllowPlayLocally <i>yes|no</i></dt>
<dd>

<p>If you set AllowPlayLocally to &quot;yes&quot;, then the playlists generated by the module will point to the physical files when handling requests from a user that happens to be working on the same machine. This is more efficient, and allows the user to pause playback, fast forward, and so on. Otherwise, the module will treat local users and remote users the same. The default is &quot;no&quot;.</p>

</dd>
<dt id="CheckStreamClient-yes|no"><a id="CheckStreamClient"></a><a id="CheckStreamClient-yes-no"></a>CheckStreamClient <i>yes|no</i></dt>
<dd>

<p>Setting CheckStreamClient to &quot;yes&quot; enables code that checks whether the client claims to be able to accept streaming MPEG data. This check isn&#39;t foolproof, but supports at least the most popular MP3 decoders (WinAmp, RealPlayer, xmms, mpg123). It also makes it harder for users to download songs by pretending to be a streaming player.</p>

<p>The default is &quot;no&quot;.</p>

</dd>
<dt id="ReadMP3Info-yes|no"><a id="ReadMP3Info"></a><a id="ReadMP3Info-yes-no"></a>ReadMP3Info <i>yes|no</i></dt>
<dd>

<p>This controls whether to extract field information from the MP3 files. The default is &quot;yes&quot;.</p>

<p>If &quot;no&quot; is specified, all fields in the directory listing will be blank except for <i>filename</i> and <i>description</i>, which will both be set to the physical filename of the MP3 file.</p>

</dd>
<dt id="StreamTimeout-integer"><a id="StreamTimeout"></a>StreamTimeout <i>integer</i></dt>
<dd>

<p>For demo mode, you can specify a stream timeout in seconds. Apache::MP3 will cease streaming the file after the time specified. Because this feature uses the average bitrate of the song, it may be off by a second or two when streaming variable bitrate MP3s.</p>

</dd>
</dl>

<h2 id="Configuration-Variables-Affecting-Paths-and-Directories"><a id="Configuration"></a>Configuration Variables Affecting Paths and Directories</h2>

<dl>

<dt id="BaseDir-URL"><a id="BaseDir"></a>BaseDir <i>URL</i></dt>
<dd>

<p>The <b>BaseDir</b> variable sets the URL in which Apache::MP3 will look for its icons and stylesheet. You may use any absolute local or remote URL. Relative URLs are not accepted.</p>

<p>The default is &quot;/apache_mp3.&quot;</p>

</dd>
<dt id="CacheDir-path"><a id="CacheDir"></a>CacheDir <i>path</i></dt>
<dd>

<p>This variable sets the directory path for Apache::MP3&#39;s cache of MP3 file information. This must be an absolute path in the physical file system and be writable by Apache. If not specified, Apache::MP3 will not cache the file information, resulting in slower performance on large directories.</p>

</dd>
<dt id="HelpImgURL-URL:widthxheight"><a id="HelpImgURL"></a>HelpImgURL <i>URL:widthxheight</i></dt>
<dd>

<p>The URL of the image that&#39;s inlined on the page that appears when the user presses the &quot;Quick Help Summary&quot; link at the bottom of the page. You can declare the size of this image by adding &quot;:WxH&quot; to the end of the URL, where W and H are the width and height, respectively.</p>

<p>Default: apache_mp3_help.gif:614x498</p>

<p>Note: I prepared this image on an airplane, so it isn&#39;t as clean as I would like. Volunteers to make a better help page are welcomed!</p>

</dd>
<dt id="StreamBase-URL"><a id="StreamBase"></a>StreamBase <i>URL</i></dt>
<dd>

<p>A URL to use as the base for streaming. The default is to use the same host for both directory listings and streaming. This may be of use when running behind a firewall and the web server can&#39;t figure out the correct address for the playlist automatically.</p>

<p>Example:</p>

<p>If the song requested is http://www.foobar.com/Songs/Madonna_live.m3u?stream=1</p>

<p>and <b>StreamBase</b> is set to <i>http://streamer.myhost.net</i>, then the URL placed in the playlist will be</p>

<pre><code> http://streamer.myhost.net/Songs/Madonna_live.m3u?stream=1</code></pre>

<p>The path part of the URL is simply appended to StreamBase. If you want to do more sophisticated URL processing, use <i>mod_rewrite</i> or equivalent.</p>

</dd>
<dt id="LocalNet-URL"><a id="LocalNet"></a>LocalNet <i>URL</i></dt>
<dd>

<p>This configuration variable is used in conjunction with <b>StreamBase</b> to disable <b>StreamBase</b> for clients on the local network. This is needed for firewall configurations in which the web server is accessed by one address &amp; port by hosts behind the firewall, and by another address &amp; port by hosts outside the firewall.</p>

<p>The argument is a dotted subnet address, or a space-delimited list of subnets. For example:</p>

<pre><code>  PerlSetVar LocalNet &quot;192.168.1 192.168.2 127.0.0.1&quot;</code></pre>

<p>Address matching is done by matching the address from left to right, with an implied dot added to the end of the subnet address. More complex subnet matching using netmasks is desirable, but not implemented.</p>

</dd>
</dl>

<h2 id="Configuration-Variables-Affecting-the-Visual-Display"><a id="Configuration1"></a>Configuration Variables Affecting the Visual Display</h2>

<dl>

<dt id="ArrowIcon-URL"><a id="ArrowIcon"></a>ArrowIcon <i>URL</i></dt>
<dd>

<p>Set the icon used for the arrows displayed between the components of the directory path at the top of the directory listing.</p>

</dd>
<dt id="CoverImage-filename"><a id="CoverImage"></a>CoverImage <i>filename</i></dt>
<dd>

<p>Before displaying a directory, Apache::MP3 will look inside the directory for an image file. This feature allows you to display digitized album covers or other customized icons. The default is &quot;cover.jpg&quot;, but the image file name can be changed with <i>CoverImage</i>. If the file does not exist, the image specified by <i>TitleIcon</i> will be displayed instead.</p>

</dd>
<dt id="CoverImageSmall-filename"><a id="CoverImageSmall"></a>CoverImageSmall <i>filename</i></dt>
<dd>

<p>Before displaying the list of subdirectories, Apache::MP3 will check inside of each for an image file of this name. If one is present, the image will displayed rather than the generic <i>DirectoryIcon</i>. The default is &quot;cover_small.jpg&quot;.</p>

</dd>
<dt id="DescriptionFormat-string"><a id="DescriptionFormat"></a>DescriptionFormat <i>string</i></dt>
<dd>

<p>The &quot;Description&quot; field, which is used both in the Description column of the directory index and in the metadata sent to the player during streaming, has a default format of <i>title</i>-<i>artist</i>-<i>album</i>. The description is constructed in such a way that the hyphen is omitted if the corresponding field of the song&#39;s MP3 tag is empty.</p>

<p>You can customize this behavior by providing a <i>DescriptionFormat</i> string. These strings combine constant characters with %x format codes in much the way that sprintf() does. For example, the directive shown below will create descriptions similar to <i>[Madonna] Like a Virgin (1980)</i>.</p>

<pre><code>  PerlSetVar DescriptionFormat &quot;[%a] %t (%y)&quot;</code></pre>

<p>The full list of format codes follows:</p>

<p>Table 2: <i>DescriptionFormat</i> Field Codes</p>

<pre><code>  Code         Description
  ----         -----------

  %a           Artist name
  %c           Comment
  %d           Duration, in format 00:00 (like 15:20 for 15 mins 20 sec)
  %f           Name of physical file (minus path)
  %g           Genre
  %l           Album name
  %m           Minutes portion of duration, usually used with %s
  %n           Track number
  %q           Sample rate, in kHz
  %r           Bitrate, in kbps
  %s           Seconds portion of duration, usually used with %m
  %S           Duration, expressed as total seconds
  %t           Title
  %y           Year</code></pre>

</dd>
<dt id="DirectoryIcon-URL"><a id="DirectoryIcon"></a>DirectoryIcon <i>URL</i></dt>
<dd>

<p>Set the icon displayed next to subdirectories in directory listings, &quot;cd_icon_small.gif&quot; by default. This can be overridden on a directory-by-directory basis by placing a <i>CoverImageSmall</i> image into the directory that you want to customize.</p>

</dd>
<dt id="PlaylistIcon-URL"><a id="PlaylistIcon"></a>PlaylistIcon <i>URL</i></dt>
<dd>

<p>Set the icon displayed next to playlists in the playlist listings, &quot;playlist.gif&quot; by default. You can change this icon on a directory-by-directory basis by placing a file with this name in the current directory.</p>

</dd>
<dt id="PlaylistImage-filename"><a id="PlaylistImage"></a>PlaylistImage <i>filename</i></dt>
<dd>

<p>Before displaying a playlist, the module will check inside the current directory for an image file named &quot;playlist.jpg&quot; to use as its icon. This directive changes the name of the playlist image file. If no image is found, the icon specified by <i>PlaylistIcon</i> is used instead.</p>

</dd>
<dt id="Fields-title,artist,duration,bitrate"><a id="Fields"></a><a id="Fields-title-artist-duration-bitrate"></a>Fields <i>title,artist,duration,bitrate</i></dt>
<dd>

<p>Specify what MP3 information fields to display in the song listing. This should be a list delimited by commas, &quot;|&quot; symbols, or any other non-word character.</p>

<p>The following are valid fields:</p>

<p>Table 3: Field Names For use with the <i>Fields</i> Configuration Variable</p>

<pre><code>    Field        Description
    -----        -----------

    album        The album
    artist       The artist
    bitrate      The bitrate, expressed in kbps
    comment      The comment field
    duration     Duration of the song in hour, minute, second format
    description  Description as specified by DescriptionFormat
    filename     The physical name of the .mp3 file
    genre        The genre
    min          The minutes portion of the duration
    seconds      Total duration of the song in seconds
    sec          The seconds portion of the duration
    samplerate   The sampling rate, in KHz
    title        The title of the song
    track        The track number
    year         The album year</code></pre>

<p>Note that MP3 rip and encoding software differ in what fields they capture and the exact format of such fields as the title and album. Field names are case insensitive.</p>

<p>Previous versions of this module used &quot;kbps&quot; instead of &quot;bitrate&quot;. This has been changed.</p>

</dd>
<dt id="HomeLabel-string"><a id="HomeLabel"></a>HomeLabel <i>string</i></dt>
<dd>

<p>This is the label for the link used to return to the site&#39;s home page. You may use plain text or any fragment of HTML, such as an &lt;IMG&gt; tag.</p>

</dd>
<dt id="LongList-integer"><a id="LongList"></a>LongList <i>integer</i></dt>
<dd>

<p>The number of lines in the list of MP3 files after which it is considered &quot;long&quot;. In long lists, the control buttons are placed at the top as well as at the bottom of the table. Defaults to 10.</p>

</dd>
<dt id="MissingComment-string"><a id="MissingComment"></a>MissingComment <i>string</i></dt>
<dd>

<p>This is the text string to use when an MP3 or Vorbis comment is missing; it is &quot;unknown&quot; (or its translation) by default. For example, if the module is configured to display the artist name, but a music file is missing this field, &quot;unknown&quot; (or its translation) will be printed instead. To turn this feature off, use an argument of &quot;off&quot;; missing fields will then be blank.</p>

<pre><code>  PerlSetVar MissingComment off</code></pre>

</dd>
<dt id="PathStyle-Staircase|Arrows"><a id="PathStyle"></a><a id="PathStyle-Staircase-Arrows"></a>PathStyle <i>Staircase|Arrows</i></dt>
<dd>

<p>Controls the style with which the parent directories are displayed. The options are &quot;Staircase&quot; (the default), which creates a staircase-style display (each child directory is on a new line and offset by 0.3 em). The other is &quot;Arrows&quot;, in which the entire directory list is on a single line and separated by graphic arrows. Try them both and choose the one you prefer.</p>

</dd>
<dt id="SongIcon-URL"><a id="SongIcon"></a>SongIcon <i>URL</i></dt>
<dd>

<p>Set the icon displayed at the beginning of each line of the MP3 file list, &quot;sound.gif&quot; by default.</p>

</dd>
<dt id="SubdirColumns-integer"><a id="SubdirColumns"></a>SubdirColumns <i>integer</i></dt>
<dd>

<p>The number of columns in which to display subdirectories (the small &quot;CD icons&quot;). A value other than 1 suppresses the display of subdirectory access-time and modification-time info. Default 1.</p>

</dd>
<dt id="PlaylistColumns-integer"><a id="PlaylistColumns"></a>PlaylistColumns <i>integer</i></dt>
<dd>

<p>The number of columns in which to display playlists. Default 3.</p>

</dd>
<dt id="Stylesheet-URL"><a id="Stylesheet"></a>Stylesheet <i>URL</i></dt>
<dd>

<p>Set the URL of the cascading stylesheet to use, &quot;apache_mp3.css&quot; by default. If the URL begins with a slash it is treated as an absolute URL. Otherwise it is interpreted as relative to the BaseDir directory.</p>

</dd>
<dt id="TitleIcon-URL"><a id="TitleIcon"></a>TitleIcon <i>URL</i></dt>
<dd>

<p>Set the icon displayed next to the current directory&#39;s name in the absence of a coverimage, &quot;cd_icon.gif&quot; by default. In this, and the other icon-related directives, relative URLs are treated as relative to <i>BaseDir</i>.</p>

</dd>
<dt id="DefaultLanguage-languagetag"><a id="DefaultLanguage"></a>DefaultLanguage <i>languagetag</i></dt>
<dd>

<p>This determines what language the interface should try appearing in, if none of the languages from the browser&#39;s Accept-Language header can be supported. For information on language tags, see <a href="https://metacpan.org/pod/I18N::LangTags::List">I18N::LangTags::List</a>. Example value: &quot;zh-cn&quot; for PRC-style Chinese.</p>

</dd>
</dl>

<h2 id="Stylesheet-Based-Configuration"><a id="Stylesheet1"></a>Stylesheet-Based Configuration</h2>

<p>You can change the appearance of the page by changing the cascading stylesheet that accompanies this module, <i>apache_mp3.css</i>. The following table describes the tags that can be customized:</p>

<p>Table 4: Stylesheet Class Names</p>

<pre><code> Class Name           Description
 ----------           ----------

 BODY                 General defaults
 H1                   Current directory path
 H2                   &quot;CD Directories&quot; and &quot;Song List&quot; headings
 TR.title             Style for the top line of the song listing
 TR.normal            Style for odd-numbered song listing lines
 TR.highlight         Style for even-numbered song listing lines
 .directory           Style for the title of the current directory
 .subdirectory        Style for the title of subdirectories
 P                    Ordinary paragraphs
 A                    Links
 INPUT                Fill-out form fields</code></pre>

<h2 id="Subclassing-this-Module"><a id="Subclassing"></a>Subclassing this Module</h2>

<p>For more extensive customization, you can subclass this module. The Apache::MP3::Sorted module illustrates how to do this.</p>

<p>Briefly, your module should inherit from Apache::MP3 (or Apache::MP3::Sorted) either by setting the <code>@ISA</code> package global or, in Perl 5.6 and higher, with the <code>use base</code> directive. Your module can then override existing methods and define new ones.</p>

<p>This module uses the <i>mod_perl</i> method invocation syntax for handler invocation. Because of this, if you override the handler() method, be sure to give it a prototype of ($$). If you override new(), be sure to place the Apache::Request object in an instance variable named &#39;r&#39;. See the MP3.pm module for details.</p>

<p>One implication of using the method invocation syntax is that the Apache::MP3 object is created at server configuration time. This means that you cannot tweak the code and simply restart the server, but must formally stop and relaunch the server every time you change the code or install a new version. This disadvantage is balanced by a savings in memory consumption and performance.</p>

<p>See <i>The Apache::MP3 API</i> below for more information on overriding Apache::MP3 methods.</p>

<h1 id="Linking-to-this-module"><a id="Linking"></a>Linking to this module</h1>

<p>You may wish to create links to MP3 files and directories manually. The rules for creating HREFs are different from those used in earlier versions of Apache::MP3, a decision forced by the fact that the playlist format used by popular MP3 decoders has changed.</p>

<p>The following rules apply:</p>

<dl>

<dt id="Download-an-MP3-file"><a id="Download"></a>Download an MP3 file</dt>
<dd>

<p>Create an HREF using the unchanged name of the MP3 file. For example, to download the song at /songs/Madonna/like_a_virgin.mp3, use:</p>

<pre><code> &lt;a href=&quot;/Songs/Madonna/like_a_virgin.mp3&quot;&gt;Like a Virgin&lt;/a&gt;</code></pre>

</dd>
<dt id="Stream-an-MP3-file"><a id="Stream"></a>Stream an MP3 file</dt>
<dd>

<p>Replace the MP3 file&#39;s extension with .m3u and add the query string &quot;play=1&quot;. Apache::MP3 will generate a playlist for the streaming MP3 decoder to load. Example:</p>

<pre><code> &lt;a href=&quot;/Songs/Madonna/like_a_virgin.m3u?play=1&quot;&gt;
         Like a streaming Virgin&lt;/a&gt;</code></pre>

</dd>
<dt id="Stream-a-directory"><a id="Stream1"></a>Stream a directory</dt>
<dd>

<p>Append &quot;/playlist.m3u?Play+All=1&quot; to the end of the directory name:</p>

<pre><code> &lt;a href=&quot;/Songs/Madonna/playlist.m3u?Play+All=1&quot;&gt;Madonna Lives!&lt;/a&gt;</code></pre>

<p>The capitalization of &quot;Play All&quot; is significant. Apache::Mp3 will generate a playlist containing all MP3 files within the directory.</p>

</dd>
<dt id="Stream-a-directory-heirarchy-recursively"><a id="Stream2"></a>Stream a directory heirarchy recursively</dt>
<dd>

<p>Append &quot;/playlist.m3u?Play+All+Recursive=1&quot; to the end of the directory name:</p>

<pre><code> &lt;a href=&quot;/Songs/HipHop/playlist.m3u?Play+All+Recursive=1&quot;&gt;Rock me&lt;/a&gt;</code></pre>

<p>The capitalization of &quot;Play All Recursive&quot; is significant. Apache::MP3 will generate a playlist containing all MP3 files within the directory and all its subdirectories.</p>

</dd>
<dt id="Shuffle-and-stream-a-directory"><a id="Shuffle"></a>Shuffle and stream a directory</dt>
<dd>

<p>Append &quot;/playlist.m3u?Shuffle+All=1&quot; to the end of the directory name:</p>

<pre><code> &lt;a href=&quot;/Songs/HipHop/playlist.m3u?Shuffle+All&quot;&gt;Rock me&lt;/a&gt;</code></pre>

<p>Apache::MP3 will generate a playlist containing all MP3 files within the directory and all its subdirectories, and then randomize its order.</p>

</dd>
<dt id="Shuffle-an-entire-directory-heirarchy-recursively"><a id="Shuffle1"></a>Shuffle an entire directory heirarchy recursively</dt>
<dd>

<p>Append &quot;/playlist.m3u?Shuffle+All+Recursive=1&quot; to the end of the directory name:</p>

<pre><code> &lt;a href=&quot;/Songs/HipHop/playlist.m3u?Shuffle+All+Recursive=1&quot;&gt;Rock me&lt;/a&gt;</code></pre>

<p>Apache::MP3 will generate a playlist containing all MP3 files within the directory and all its subdirectories, and then randomize its order.</p>

</dd>
<dt id="Play-a-set-of-MP3s-within-a-directory"><a id="Play"></a>Play a set of MP3s within a directory</dt>
<dd>

<p>Append &quot;/playlist.m3u?Play+Selected=1;file=file1;file=file2...&quot; to the directory name:</p>

<pre><code> &lt;a
 href=&quot;/Songs/Madonna/playlist.m3u?Play+Selected=1;file=like_a_virgin.mp3;file=evita.mp3&quot;&gt;
 Two favorites&lt;/a&gt;</code></pre>

<p>Again, the capitalization of &quot;Play Selected&quot; counts.</p>

</dd>
<dt id="Display-a-sorted-directory"><a id="Display"></a>Display a sorted directory</dt>
<dd>

<p>Append &quot;?sort=field&quot; to the end of the directory name, where field is any of the MP3 field names:</p>

<pre><code> &lt;a href=&quot;/Songs/Madonna/?sort=duration&quot;&gt;Madonna lives!&lt;/a&gt;</code></pre>

</dd>
</dl>

<h1 id="The-Apache::MP3-API"><a id="The"></a>The Apache::MP3 API</h1>

<p>The Apache::MP3 object is a blessed hash containing a single key, <code>r</code>, which points at the current request object. This can be retrieved conveniently using the r() method.</p>

<p>Apache::MP3 builds up its directory listing pages in pieces, using a hierarchical scheme. The following diagram summarizes which methods are responsible for generating the various parts. It might help to study it alongside a representative HTML page:</p>

<pre><code> list_directory()
 -------------------------  page top --------------------------------
    page_top()
    directory_top()

    &lt;CDICON&gt; &lt;DIRECTORY&gt; -&gt; &lt;DIRECTORY&gt; -&gt; &lt;DIRECTORY&gt;
    [Shuffle All] [Stream All]

    list_subdirs()

         subdir_list_top()
         ------------------------------------------------------------
         &lt;CD Directories (6)&gt;

         subdir_list()
               &lt;cdicon&gt; &lt;title&gt;   &lt;cdicon&gt; &lt;title&gt;  &lt;cdicon&gt; &lt;title&gt;
               &lt;cdicon&gt; &lt;title&gt;   &lt;cdicon&gt; &lt;title&gt;  &lt;cdicon&gt; &lt;title&gt;

         subdir_list_bottom()  # does nothing
         ------------------------------------------------------------

    list_playlists()

         playlist_list_top()
         ------------------------------------------------------------
         &lt;CD Playlists (6)&gt;

         playlist_list()
               &lt;cdicon&gt; &lt;title&gt;   &lt;cdicon&gt; &lt;title&gt;  &lt;cdicon&gt; &lt;title&gt;
               &lt;cdicon&gt; &lt;title&gt;   &lt;cdicon&gt; &lt;title&gt;  &lt;cdicon&gt; &lt;title&gt;

         playlist_list_bottom()  # does nothing
         ------------------------------------------------------------

    list_mp3s()
         mp3_list_top()
         ------------------------------------------------------------
         &lt;Song List (4)&gt;

         mp3_list()
             mp3_list_top()
               mp3_table_header()
                  &lt;Select&gt;                  Title          Kbps

               format_song() # called for each row
                  &lt;icon&gt;[] [fetch][stream]  Like a virgin  128
                  &lt;icon&gt;[] [fetch][stream]  American Pie   128
                  &lt;icon&gt;[] [fetch][stream]  Santa Evita     96
                  &lt;icon&gt;[] [fetch][stream]  Boy Toy        168

             mp3_list_bottom()
               [Play Selected] [Shuffle Selected]

    directory_bottom()
 -------------------------  page bottom -----------------------------</code></pre>

<h2 id="Method-Calls"><a id="Method"></a>Method Calls</h2>

<p>This section lists each of the Apache::MP3 method calls briefly.</p>

<dl>

<dt id="$response_code-=-handler($request)"><a id="response_code---handler-request"></a>$response_code = handler($request)</dt>
<dd>

<p>This is a the standard mod_perl handler() subroutine. It creates a new Apache::MP3 object, and then invokes its run() method.</p>

</dd>
<dt id="$mp3-=-Apache::MP3-&gt;new(@args)"><a id="mp3---Apache::MP3--new-args"></a>$mp3 = Apache::MP3-&gt;new(@args)</dt>
<dd>

<p>This is a constructor. It stores the passed args in a hash and returns a new Apache::MP3 object. If a single argument is passed it assumes that it is an Apache::Request object and stores it under the key &quot;r&quot;. You should not have to modify this method.</p>

</dd>
<dt id="$request-=-$mp3-&gt;r()"><a id="request----mp3--r"></a>$request = $mp3-&gt;r()</dt>
<dd>

<p>Return the stored request object.</p>

</dd>
<dt id="$boolean-=-$mp3-&gt;is_local()"><a id="boolean----mp3--is_local"></a>$boolean = $mp3-&gt;is_local()</dt>
<dd>

<p>Returns true if the requesting client is on the same machine as the server.</p>

</dd>
<dt id="$response_code-=-$mp3-&gt;run()"><a id="response_code----mp3--run"></a>$response_code = $mp3-&gt;run()</dt>
<dd>

<p>This is the method that interprets the CGI parameters and dispatches to the routines that draw the directory listing, generate playlists, and stream songs.</p>

</dd>
<dt id="$response_code-=-$mp3-&gt;process_directory($dir)"><a id="response_code----mp3--process_directory-dir"></a>$response_code = $mp3-&gt;process_directory($dir)</dt>
<dd>

<p>This is the top-level method for generating the directory listing. It performs various consistency checks on the passed directory URL and returns an Apache response code. The list_directory() method actually does most of the formatting work.</p>

</dd>
<dt id="$response_code-=-$mp3-&gt;download_file($file)"><a id="response_code----mp3--download_file-file"></a>$response_code = $mp3-&gt;download_file($file)</dt>
<dd>

<p>This method is called to download a file (not stream it). It is passed the URL of the requested file and returns an Apache response code. It checks whether downloads are allowed and if so allows Apache to take its default action.</p>

</dd>
<dt id="$response_code-=-$mp3-&gt;stream($file)"><a id="response_code----mp3--stream-file"></a>$response_code = $mp3-&gt;stream($file)</dt>
<dd>

<p>This method is called to stream an MP3 file. It is passed the URL of the requested file and returns an Apche response code.</p>

</dd>
<dt id="$fh-=-$mp3-&gt;open_file($file)"><a id="fh----mp3--open_file-file"></a>$fh = $mp3-&gt;open_file($file)</dt>
<dd>

<p>This method is called by stream() to open the file to be streamed. It accepts a file path and returns a filehandle. This can be overridden to do interesting things to the MP3 file, such as resample it or collect statistics.</p>

</dd>
<dt id="$mp3-&gt;send_playlist($urls,$shuffle)"><a id="mp3--send_playlist-urls-shuffle"></a>$mp3-&gt;send_playlist($urls,$shuffle)</dt>
<dd>

<p>This method generates a playlist that is sent to the browser. It is called from various places. <code>$urls</code> is an array reference containing the MP3 URLs to incorporate into the playlist, and <code>$shuffle</code> is a flag indicating that the order of the playlist should be randomized prior to sending it. No return value is returned.</p>

</dd>
<dt id="@urls-=-$mp3-&gt;sort_mp3s($mp3_info)"><a id="urls----mp3--sort_mp3s-mp3_info"></a>@urls = $mp3-&gt;sort_mp3s($mp3_info)</dt>
<dd>

<p>This method sorts the hashref of MP3 files returned from find_mp3s(), returning an array. The implementation of this method in Apache::MP3 sorts by physical file name only. Apache::MP3::Sorted has a more sophisticated implementation.</p>

</dd>
<dt id="@mp3s-=-$mp3-&gt;load_playlist($playlist)"><a id="mp3s----mp3--load_playlist-playlist"></a>@mp3s = $mp3-&gt;load_playlist($playlist)</dt>
<dd>

<p>This method loads a playlist file (.m3u) from disk and returns a list of MP3 files contained in the playlist.</p>

</dd>
<dt id="$mp3-&gt;playlist_list_bottom($playlists)"><a id="mp3--playlist_list_bottom-playlists"></a>$mp3-&gt;playlist_list_bottom($playlists)</dt>
<dd>

<p>This method generates the footer at the bottom of the list of playlists given by <code>$playlists</code>. Currently it does nothing.</p>

</dd>
<dt id="$mp3-&gt;playlist_list($playlists)"><a id="mp3--playlist_list-playlists"></a>$mp3-&gt;playlist_list($playlists)</dt>
<dd>

<p>This method displays the playlists given by <code>$playlists</code> in a nicely formatted table.</p>

</dd>
<dt id="$html-=-$mp3-&gt;format_playlist($playlist)"><a id="html----mp3--format_playlist-playlist"></a>$html = $mp3-&gt;format_playlist($playlist)</dt>
<dd>

<p>This method formats the indicated playlist by creating a fragment of HTML containing the playlist icon, the stream links and the playlist name. It returns a HTML fragment used by playlist_list().</p>

</dd>
<dt id="$response_code-=-$mp3-&gt;list_directory($dir)"><a id="response_code----mp3--list_directory-dir"></a>$response_code = $mp3-&gt;list_directory($dir)</dt>
<dd>

<p>This is the top level formatter for directory listings. It is passed the URL of a directory and returns an Apache response code.</p>

</dd>
<dt id="$mp3-&gt;page_top($dir)"><a id="mp3--page_top-dir"></a>$mp3-&gt;page_top($dir)</dt>
<dd>

<p>This method begins the HTML at the top of the page from the initial &lt;head&gt; section through the opening &lt;body&gt;.</p>

</dd>
<dt id="$mp3-&gt;directory_top($dir)"><a id="mp3--directory_top-dir"></a>$mp3-&gt;directory_top($dir)</dt>
<dd>

<p>This method lists the top part of the directory, including the title, the directory navigation list, and the big CD Icon in the upper left.</p>

</dd>
<dt id="$mp3-&gt;generate_navpath_staircase($dir)"><a id="mp3--generate_navpath_staircase-dir"></a>$mp3-&gt;generate_navpath_staircase($dir)</dt>
<dd>

<p>This method generates the list of parent directories, displaying them as links so that the user can navigate. It takes the URL of the current directory and returns no result.</p>

</dd>
<dt id="$mp3-&gt;generate_navpath_arrows($dir)"><a id="mp3--generate_navpath_arrows-dir"></a>$mp3-&gt;generate_navpath_arrows($dir)</dt>
<dd>

<p>This method does the same, except that the parent directories are displayed on a single line, separated by arrows.</p>

</dd>
<dt id="$mp3-&gt;directory_bottom($dir)"><a id="mp3--directory_bottom-dir"></a>$mp3-&gt;directory_bottom($dir)</dt>
<dd>

<p>This method generates the bottom part of the directory listing, including the module attribution and help information.</p>

</dd>
<dt id="$mp3-&gt;subdir_list_top($directories)"><a id="mp3--subdir_list_top-directories"></a>$mp3-&gt;subdir_list_top($directories)</dt>
<dd>

<p>This method generates the heading at the top of the list of subdirectories. <code>$directories</code> is an arrayref containing the subdirectories to display.</p>

</dd>
<dt id="$mp3-&gt;subdir_list_bottom($directories)"><a id="mp3--subdir_list_bottom-directories"></a>$mp3-&gt;subdir_list_bottom($directories)</dt>
<dd>

<p>This method generates the footer at the bottom of the list of subdirectories given by <code>$directories</code>. Currently it does nothing.</p>

</dd>
<dt id="$mp3-&gt;subdir_list($directories)"><a id="mp3--subdir_list-directories"></a>$mp3-&gt;subdir_list($directories)</dt>
<dd>

<p>This method invokes sort_subdirs() to sort the subdirectories given by <code>$directories</code> and displays them in a nicely-formatted table.</p>

</dd>
<dt id="@directories-=-$mp3-&gt;sort_subdirs($directories)"><a id="directories----mp3--sort_subdirs-directories"></a>@directories = $mp3-&gt;sort_subdirs($directories)</dt>
<dd>

<p>This method sorts the subdirectories given in <code>$directories</code> and returns a sorted <b>list</b> (not an arrayref).</p>

</dd>
<dt id="$html-=-$mp3-&gt;format_subdir($directory)"><a id="html----mp3--format_subdir-directory"></a>$html = $mp3-&gt;format_subdir($directory)</dt>
<dd>

<p>This method formats the indicated subdirectory by creating a fragment of HTML containing the little CD icon, the shuffle and stream links, and the subdirectory&#39;s name. It returns an HTML fragment used by subdir_list().</p>

</dd>
<dt id="$mp3-&gt;get_help"><a id="mp3--get_help"></a>$mp3-&gt;get_help</dt>
<dd>

<p>This subroutine generates the &quot;Quick Help Summary&quot; link at the bottom of the page.</p>

</dd>
<dt id="$mp3-&gt;list_subdirs($subdirectories)"><a id="mp3--list_subdirs-subdirectories"></a>$mp3-&gt;list_subdirs($subdirectories)</dt>
<dd>

<p>This is the top-level subroutine for listing subdirectories (the part of the page in which the little CD icons appears). <code>$subdirectories</code> is an array reference containing the subdirectories to display</p>

</dd>
<dt id="$mp3-&gt;list_playlists($playlists)"><a id="mp3--list_playlists-playlists"></a>$mp3-&gt;list_playlists($playlists)</dt>
<dd>

<p>This is the top-level subroutine for listing playlists. <code>$playlists</code> is an array reference containing the playlists to display.</p>

</dd>
<dt id="$mp3-&gt;list_mp3s($mp3s)"><a id="mp3--list_mp3s-mp3s"></a>$mp3-&gt;list_mp3s($mp3s)</dt>
<dd>

<p>This is the top-level subroutine for listing MP3 files. <code>$mp3s</code> is a hashref in which the key is the path of the MP3 file and the value is a hashref containing MP3 tag info about it. This generates the buttons at the top of the table and then calls mp3_table_header() and mp3_list_bottom().</p>

</dd>
<dt id="$mp3-&gt;mp3_table_header"><a id="mp3--mp3_table_header"></a>$mp3-&gt;mp3_table_header</dt>
<dd>

<p>This creates the first row (table headers) of the list of MP3 files.</p>

</dd>
<dt id="$mp3-&gt;mp3_list_bottom($mp3s)"><a id="mp3--mp3_list_bottom-mp3s"></a>$mp3-&gt;mp3_list_bottom($mp3s)</dt>
<dd>

<p>This method generates the buttons at the bottom of the MP3 file listing. <code>$mp3s</code> is a hashref containing information about each file.</p>

</dd>
<dt id="$mp3-&gt;mp3_list($mp3s)"><a id="mp3--mp3_list-mp3s"></a>$mp3-&gt;mp3_list($mp3s)</dt>
<dd>

<p>This routine sorts the MP3 files contained in <code>$mp3s</code> and invokes format_song() to format it for the table.</p>

</dd>
<dt id="@buttons-=-$mp3-&gt;control_buttons"><a id="buttons----mp3--control_buttons"></a>@buttons = $mp3-&gt;control_buttons</dt>
<dd>

<p>Return the list of buttons printed at the bottom of the MP3 file listing.</p>

</dd>
<dt id="$arrayref-=-$mp3-&gt;format_song($song,$info,$count)"><a id="arrayref----mp3--format_song-song-info-count"></a>$arrayref = $mp3-&gt;format_song($song,$info,$count)</dt>
<dd>

<p>This method is called with three arguments. <code>$song</code> is the path to the MP3 file, <code>$info</code> is a hashref containing tag information from the song, and <code>$count</code> is an integer containing the song&#39;s position in the list (which currently is unusued). The method invokes format_song_controls() and format_song_fields() to generate a list of elements to be incorporated into cells of the table, and returns an array reference.</p>

</dd>
<dt id="@array-=-$mp3-&gt;format_song_controls($song,$info,$count)"><a id="array----mp3--format_song_controls-song-info-count"></a>@array = $mp3-&gt;format_song_controls($song,$info,$count)</dt>
<dd>

<p>This method is called with the same arguments as format_song(). It returns a list (not an arrayref) containing the &quot;control&quot; elements of one row of the MP3 list. The control elements are all the doo-dads on the left-hand side of the display, including the music icon, the checkbox, and the [fetch] and [stream] links.</p>

</dd>
<dt id="@array-=-$mp3-&gt;format_song_fields($song,$info,$count)"><a id="array----mp3--format_song_fields-song-info-count"></a>@array = $mp3-&gt;format_song_fields($song,$info,$count)</dt>
<dd>

<p>This method is called with the same arguments as format_song(). It returns a list (not an arrayref) containing the rest of a row of the MP3 file display. This will include the title, artist, and so forth, depending on the values of the Fields configuration. variable.</p>

</dd>
<dt id="($directories,$mp3s)-=-$mp3-&gt;read_directory($dir)"><a id="directories-mp3s-----mp3--read_directory-dir"></a>($directories,$mp3s) = $mp3-&gt;read_directory($dir)</dt>
<dd>

<p>This method reads the directory in <code>$dir</code>, generating an arrayref containing the subdirectories and a hashref containing the MP3 files and their information, which are returned as a two-element list.</p>

</dd>
<dt id="$hashref-=-$mp3-&gt;fetch_info($file)"><a id="hashref----mp3--fetch_info-file"></a>$hashref = $mp3-&gt;fetch_info($file)</dt>
<dd>

<p>This method fetches the MP3 information for <code>$file</code> and returns a hashref containing the MP3 tag information as well as some synthesized fields. The synthesized fields are <i>track</i>, which contains the same information as <i>tracknum</i>; <i>description</i>, which contains the title, album and artist merged together; and <i>duration</i>, which contains the duration of the song expressed as hours, minutes and seconds. Other fields are taken directly from the MP3 tag, but are downcased (for convenience to other routines).</p>

</dd>
<dt id="Apache::MP3-&gt;path_escape($scalarref)"><a id="Apache"></a><a id="Apache::MP3--path_escape-scalarref"></a>Apache::MP3-&gt;path_escape($scalarref)</dt>
<dd>

<p>This is a limited form of CGI::escape which does <b>not</b> escape the slash symbol (&quot;/&quot;). This allows URIs that correspond to directories to be escaped safely. The escape is done inplace on the passed scalar reference.</p>

</dd>
<dt id="@fields-=-$mp3-&gt;fields"><a id="fields----mp3--fields"></a>@fields = $mp3-&gt;fields</dt>
<dd>

<p>Return the fields to display for each MP3 file. Reads the <i>Fields</i> configuration variable, or uses a default list.</p>

</dd>
<dt id="$hashref-=-$mp3-&gt;read_cache($file)"><a id="hashref----mp3--read_cache-file"></a>$hashref = $mp3-&gt;read_cache($file)</dt>
<dd>

<p>Reads the cache for MP3 information about the indicated file. Returns a hashref of the same format used by fetch_info().</p>

</dd>
<dt id="$boolean-=-$mp3-&gt;write_cache($file,$info)"><a id="boolean----mp3--write_cache-file-info"></a>$boolean = $mp3-&gt;write_cache($file,$info)</dt>
<dd>

<p>Writes MP3 information to cache. <code>$file</code> and <code>$info</code> are the path to the file and its MP3 tag information, respectively. Returns a boolean indicating the success of the operation.</p>

</dd>
<dt id="$boolean-=-$mp3-&gt;download_ok"><a id="boolean----mp3--download_ok"></a>$boolean = $mp3-&gt;download_ok</dt>
<dd>

<p>Returns true if downloading files is allowed.</p>

</dd>
<dt id="$boolean-=-$mp3-&gt;stream_ok"><a id="boolean----mp3--stream_ok"></a>$boolean = $mp3-&gt;stream_ok</dt>
<dd>

<p>Returns true if streaming files is allowed.</p>

</dd>
<dt id="$boolean-=-$mp3-&gt;check_stream_client"><a id="boolean----mp3--check_stream_client"></a>$boolean = $mp3-&gt;check_stream_client</dt>
<dd>

<p>Returns true if the module should check the browser/MP3 player for whether it accepts streaming.</p>

</dd>
<dt id="$boolean-=-$mp3-&gt;is_stream_client"><a id="boolean----mp3--is_stream_client"></a>$boolean = $mp3-&gt;is_stream_client</dt>
<dd>

<p>Returns true if this MP3 player can accept streaming. Note that this is not a foolproof method because it checks a variety of non-standardized headers and user agent names!</p>

</dd>
<dt id="$boolean-=-$mp3-&gt;read_mp3_info"><a id="boolean----mp3--read_mp3_info"></a>$boolean = $mp3-&gt;read_mp3_info</dt>
<dd>

<p>Returns true if the module should read MP3 info (true by default).</p>

</dd>
<dt id="$seconds-=-$mp3-&gt;stream_timeout"><a id="seconds----mp3--stream_timeout"></a>$seconds = $mp3-&gt;stream_timeout</dt>
<dd>

<p>Returns the number of seconds after which streaming should time out. Used for &quot;demo mode&quot;.</p>

</dd>
<dt id="$lines-=-$mp3-&gt;file_list_is_long"><a id="lines----mp3--file_list_is_long"></a>$lines = $mp3-&gt;file_list_is_long</dt>
<dd>

<p>Returns the number of lines in the MP3 file listing after which the list is considered to be &quot;long&quot;. When a long list is encountered, the module places the control buttons at both the top and bottom of the MP3 file table, rather than at the bottom only. This method</p>

</dd>
<dt id="$html-=-$mp3-&gt;home_label"><a id="html----mp3--home_label"></a>$html = $mp3-&gt;home_label</dt>
<dd>

<p>Returns a fragment of HTML to use as the &quot;Home&quot; link in the list of parent directories.</p>

</dd>
<dt id="$style-=-$mp3-&gt;path_style"><a id="style----mp3--path_style"></a>$style = $mp3-&gt;path_style</dt>
<dd>

<p>Returns the style of the list of parent directories. Either &quot;arrows&quot; or &quot;staircase&quot;.</p>

</dd>
<dt id="$path-=-$mp3-&gt;cache_dir"><a id="path----mp3--cache_dir"></a>$path = $mp3-&gt;cache_dir</dt>
<dd>

<p>Returns the directory for use in caching MP3 tag information</p>

</dd>
<dt id="$int-=-$mp3-&gt;subdir_columns"><a id="int----mp3--subdir_columns"></a>$int = $mp3-&gt;subdir_columns</dt>
<dd>

<p>Returns the number of columns to use in displaying subdirectories (little CD icons). If the return value is 1, directory access-time and modification-time are displayed. If not equal to one, these data are suppressed.</p>

</dd>
<dt id="$dir-=-$mp3-&gt;default_dir"><a id="dir----mp3--default_dir"></a>$dir = $mp3-&gt;default_dir</dt>
<dd>

<p>Returns the base directory used for resolving relative paths in the directories to follow.</p>

</dd>
<dt id="miscellaneous-directories-and-files"><a id="miscellaneous"></a>miscellaneous directories and files</dt>
<dd>

<p>The following methods return the values of their corresponding configuration variables, resolved against the base directory, if need be:</p>

<pre><code> stylesheet()   URI to the stylesheet file
 parent_icon()  URI to the icon to use to move up in directory
                     hierarchy (no longer used)
 cd_icon        URI for the big CD icon printed in the upper left corner
 song_icon      URI for the music note icons printed for each MP3 file
 arrow_icon     URI for the arrow used in the navigation bar
 help_url       URI of the document to display when user asks for help</code></pre>

<p>The following methods return the values of their corresponding configuration variables, resolved against the current directory, but if that fails, against the base directory. This is useful for customizing the appearance icons on a per-directory basis. For example, I like my directories containing shoutcast playlists to appear differently than my directories containing mp3 and m3u files.</p>

<pre><code> cd_list_icon   URI for the little CD icons in the subdirectory listing
 playlist_icon  URI for the playlist icon</code></pre>

</dd>
<dt id="$boolean-=-$mp3-&gt;skip_directory($dir)"><a id="boolean----mp3--skip_directory-dir"></a>$boolean = $mp3-&gt;skip_directory($dir)</dt>
<dd>

<p>This method is called during directory listings. It returns true if the directory should not be displayed. Currently it skips directories beginning with a dot and various source code management directories. You may subclass this to skip over other directories.</p>

</dd>
</dl>

<h1 id="BUGS">BUGS</h1>

<p>Although it is pure Perl, this module relies on an unusual number of compiled modules. Perhaps for this reason, it appears to be sensitive to certain older versions of modules.</p>

<h2 id="Random-segfaults-in-httpd-children"><a id="Random"></a>Random segfaults in httpd children</h2>

<p>Before upgrading to Apache/1.3.6 mod_perl/1.24, I would see random segfaults in the httpd children when using this module. This problem disappeared when I installed a newer mod_perl.</p>

<p>If you experience this problem, I have found that one workaround is to load the MP3::Info module at server startup time using the mod_perl perl.startup script made the problem go away. This is an excerpt from my perl.startup file:</p>

<pre><code> # the !/usr/local/bin/perl
 ...
 use Apache::Registry ();
 use Apache::Constants();
 use MP3::Info;
 use Apache::MP3;
 use CGI();
 use CGI::Carp ();</code></pre>

<h2 id="Can&#39;t-use-d-$r-&gt;finfo"><a id="Can"></a><a id="Can-t-use-d--r--finfo"></a>Can&#39;t use -d $r-&gt;finfo</h2>

<p>Versions of mod_perl prior to 1.22 crash when using the idiom -d $r-&gt;finfo (or any other idiom). Since there are many older versions still out there, I have replaced $r-&gt;finfo with $r-&gt;filename and marked their locations in comments. To get increased performance, change back to $r-&gt;finfo.</p>

<h2 id="Misc">Misc</h2>

<p>In the directory display, the alignment of subdirectory icon with the subdirectory title is a little bit off. I want to move the title a bit lower using some stylesheet magic. Can anyone help?</p>

<h1 id="SEE-ALSO"><a id="SEE"></a>SEE ALSO</h1>

<p><a href="https://metacpan.org/pod/Apache::MP3::Sorted">Apache::MP3::Sorted</a>, <a href="https://metacpan.org/pod/Apache::MP3::Playlist">Apache::MP3::Playlist</a>, <a href="https://metacpan.org/pod/MP3::Info">MP3::Info</a>, <a href="https://metacpan.org/pod/Apache">Apache</a>, <a href="https://metacpan.org/pod/Apache::MP3::L10N">Apache::MP3::L10N</a></p>

<h1 id="ACKNOWLEDGEMENTS">ACKNOWLEDGEMENTS</h1>

<p>Tim Ayers &lt;tayers@bridge.com&gt; found and fixed a misfeature in the way that playlists were sorted.</p>

<p>Chris Nandor identified various bugs in the module and provided patches.</p>

<p>Sean M. Burke (&lt;sburke@cpan.org&gt;) internationalized this module and coordinated the translators/localizers. Each translator/localizer/consultant is thanked in the respective <code>Apache/MP3/L10N/<i>langname</i>.pm</code> file.</p>

<p>Caleb Epstein &lt;cae@bklyn.org&gt;), for generalizing the resampling module.</p>

<p>Allen Day &lt;allenday@ucla.edu&gt;, for implementing MP3::Icecast</p>

<h1 id="AUTHOR">AUTHOR</h1>

<p>Copyright 2000, Lincoln Stein &lt;lstein@cshl.org&gt;.</p>

<p>This module is distributed under the same terms as Perl itself. Feel free to use, modify and redistribute it as long as you retain the correct attribution.</p></div>

<div id="metacpan_install-instructions-dialog" class="modal fade">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
        <h4 class="modal-title">Module Install Instructions</h4>
      </div>
      <div class="modal-body">
        <p>To install Apache::MP3, copy and paste the appropriate command in to your terminal.</p>
        <p><a href="https://metacpan.org/dist/App-cpanminus/view/bin/cpanm">cpanm</a></p>
        <pre><code>cpanm Apache::MP3</code></pre>
        <p><a href="https://metacpan.org/pod/CPAN">CPAN shell</a></p>
        <pre><code>perl -MCPAN -e shell
install Apache::MP3</code></pre>
        <p>For more information on module installation, please visit <a href="https://www.cpan.org/modules/INSTALL.html">the detailed CPAN module installation guide</a>.</p>
      </div>
      <div class="modal-footer">
        <a href="./Apache::MP3.html#" data-dismiss="modal" class="btn">Close</a>
      </div>
    </div>
  </div>
</div>
          </main>
          <div class="content-pagination">
          </div>
        </div>
        <footer class="footer">
          <div class="footer-container">
            <div class="footer-social">
              <div class="footer-link footer-logo">
                <a href="https://metacpan.org/">
                  <img src="https://metacpan.org/static/images/metacpan-logo.svg" alt="MetaCPAN" />
                </a>
              </div>
              <a class="footer-social-link" href="https://github.com/metacpan">
                <i class="fab fa-github-square"></i>
              </a>
              <a class="footer-social-link" href="https://fosstodon.org/@metacpan">
                <i class="fab fa-mastodon"></i>
              </a>
            </div>
            <div class="footer-links">
              <div class="footer-link">
                  <a href="https://metacpan.org/about">About</a>
              </div>
              <div class="footer-link">
                  <a href="https://metacpan.org/about/sponsors">Sponsor</a>
              </div>
              <div class="footer-link">
                  <a href="https://grep.metacpan.org">grep::cpan</a>
              </div>
              <div class="footer-link">
                  <a href="https://metacpan.org/recent">Recent</a>
              </div>
              <div class="footer-link">
                  <a href="https://metacpan.org/about/faq">FAQ</a>
              </div>
              <div class="footer-link">
                  <a href="https://metacpan.org/tools">Tools</a>
              </div>
              <div class="footer-link">
                  <a href="https://fastapi.metacpan.org/">API</a>
              </div>
              <div class="footer-link">
                  <a href="https://www.perl.org/">Perl.org</a>
              </div>
            </div>
            <div class="footer-sponsors">
              <a class="footer-sponsor-link" target="_blank" href="https://www.bytemark.co.uk/" rel="noopener">
                <img class="footer-sponsor-bytemark" src="https://metacpan.org/static/images/sponsors/bytemark_logo.svg" alt="Bytemark logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://www.liquidweb.com/" rel="noopener">
                <img class="footer-sponsor-liquidweb" src="https://metacpan.org/static/images/sponsors/liquidweb_logo.png" alt="liquidweb logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://deriv.com/careers/" rel="noopener">
                <img class="footer-sponsor-deriv" src="https://metacpan.org/static/images/sponsors/deriv.svg" alt="Deriv logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://geocode.xyz" rel="noopener">
                <img class="footer-sponsor-geocode" src="https://metacpan.org/static/images/sponsors/geocodelogo.svg" alt="Geocode logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://www.fastly.com/" rel="noopener">
                <img class="footer-sponsor-fastly" src="https://metacpan.org/static/images/sponsors/fastly_logo.svg" alt="Fastly logo">
              </a>
              <a class="footer-sponsor-link" target="_blank" href="https://opencagedata.com" rel="noopener">
                <img class="footer-sponsor-opencage" src="https://metacpan.org/static/images/sponsors/open-cage.svg" alt="OpenCage logo">
              </a>
            </div>
          </div>
        </footer>
        <div class="modal fade" tabindex="-1" role="dialog" id="metacpan_keyboard-shortcuts">
          <div class="modal-dialog">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal">&times;</button>
                <h4 class="modal-title">Keyboard Shortcuts</h4>
              </div>
              <div class="modal-body row">
<div class="col-md-6">
  <table class="table keyboard-shortcuts">
    <thead>
      <tr>
        <th></th>
        <th>Global</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="keys">
          <kbd>s</kbd>
        </td>
        <td>Focus search bar</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>?</kbd>
        </td>
        <td>Bring up this help dialog</td>
      </tr>
    </tbody>
  </table>

  <table class="table keyboard-shortcuts">
    <thead>
      <tr>
        <th></th>
        <th>GitHub</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>p</kbd>
        </td>
        <td>Go to pull requests</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>i</kbd>
        </td>
        <td>go to github issues (only if github is preferred repository)</td>
      </tr>
    </tbody>
  </table>
</div>

<div class="col-md-6">
  <table class="table keyboard-shortcuts">
    <thead>
      <tr>
        <th></th>
        <th>POD</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>a</kbd>
        </td>
        <td>Go to author</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>c</kbd>
        </td>
        <td>Go to changes</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>i</kbd>
        </td>
        <td>Go to issues</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>d</kbd>
        </td>
        <td>Go to dist</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>r</kbd>
        </td>
        <td>Go to repository/SCM</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>s</kbd>
        </td>
        <td>Go to source</td>
      </tr>
      <tr>
        <td class="keys">
          <kbd>g</kbd> <kbd>b</kbd>
        </td>
        <td>Go to file browse</td>
      </tr>

    </tbody>
  </table>
</div>

<div class="col-md-12">
  <table class="table keyboard-shortcuts">
    <thead>
      <tr>
        <th></th>
        <th>Search terms</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><em>module:</em> (e.g. <a href="https://metacpan.org/search?q=module%3APlugin">module:Plugin</a>)</td>
      </tr>
      <tr>
        <td><em>distribution:</em> (e.g. <a href="https://metacpan.org/search?q=distribution%3ADancer+auth">distribution:Dancer auth</a>)</td>
      </tr>
      <tr>
        <td><em>author:</em> (e.g. <a href="https://metacpan.org/search?q=author%3ASONGMU+Redis">author:SONGMU Redis</a>)</td>
      </tr>
      <tr>
        <td><em>version:</em> (e.g. <a href="https://metacpan.org/search?q=version%3A1.00">version:1.00</a>)</td>
      </tr>
    </tbody>
  </table>
</div>
              </div>
              <div class="modal-footer"></div>
            </div>
          </div>
        </div>
    </body>
</html>
